#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <search.h>
#include <sys/time.h>

#define DEBUG_LOG(fmt, args...) sprintf(stdout, fmt, ##args)
#define DEBUG_LOG_1(fmt, ...) sprintf(stdout, fmt, ##__VA_ARGS__)

// static void *root = NULL;

int compare(const void *pa, const void *pb)
{
    return strcmp((const char *)pa, (const char *)pb);
}

void action(const void *nodep, const VISIT which, const int depth)
{
    int *datap;

    switch (which) {
        case preorder:
            break;
        case postorder:
            datap = *(int **) nodep;
            printf("%6d\n", *datap);
            break;
        case endorder:
            break;
        case leaf:
            datap = *(int **) nodep;
            printf("%6d\n", *datap);
            break;
    }
}
typedef struct __mobile_node__
{
    char mobile[16];
}Mobile;

#if 0
/* 字符串逗号分隔符解析 */
int duplication(char *sample, Mobile **mobile, int *count)
{
    int i = 0, j = 0, num = 0;
    void *val, *root = NULL, *pfind = NULL;
    char *strTempPtr = NULL, *saveptr = NULL;

    *mobile = (Mobile *)malloc(sizeof(Mobile));

    strTempPtr = strtok_r(sample, ",", &saveptr);
    while (strTempPtr)
    {
        Mobile *temp = NULL;
        temp = malloc(sizeof(Mobile));
        pfind = (void *)temp->mobile;
        strncpy(temp->mobile, strTempPtr, sizeof(Mobile));

        val = tsearch(pfind, &root, compare);
        if (*(char **)val == (char *)pfind)
        {
            /* 说明二叉树中没有此节点，那么保存到自定义数据结构中 */
            *mobile = (Mobile *)realloc(*mobile, sizeof(Mobile)*(i+1));

            strncpy((*mobile)[i].mobile, strTempPtr, sizeof(Mobile));

            ++i; ++num;
        }
        strTempPtr = strtok_r(NULL, ",", &saveptr);
    }
    *count = num;

    printf("i:%d, num:%d\n", i, num);
    for (j = 0; j < num; ++j)
        printf("num:%d, mobile:%s\n", j, (*mobile)[j].mobile);

    tdestroy(root, free);
    return 0;
}
#endif

/* 文件解析，单行数据 */
int duplication(FILE *fp, Mobile **mobile, int *count)
{
    int i = 0, num = 0;
    void *val, *root = NULL, *pfind = NULL;
    // char *strTempPtr = NULL, *saveptr = NULL;
    char mstring[128] = {0};

    *mobile = (Mobile *)malloc(sizeof(Mobile));

    while (fgets(mstring, 128, fp))
    {
        char *ptr = NULL;
        Mobile *temp = NULL;
        temp = malloc(sizeof(Mobile));
        pfind = (void *)temp->mobile;
        /* 去掉换行符 */
        ptr = strchr(mstring, '\n');
        if (ptr) *ptr = '\0';
        
        strncpy(temp->mobile, mstring, sizeof(Mobile));
        /* printf("length:%d, mstring:%s\n", (int)strlen(mstring), mstring); */

        val = tsearch(pfind, &root, compare);
        if (*(char **)val == (char *)pfind)
        {
            /* 说明二叉树中没有此节点，那么保存到自定义数据结构中 */
            *mobile = (Mobile *)realloc(*mobile, sizeof(Mobile)*(i+1));

            strncpy((*mobile)[i].mobile, mstring, sizeof(Mobile));

            ++i; ++num;
        }
        mstring[0] = '\0';
    }
    *count = num;

#if 0
    printf("i:%d, num:%d\n", i, num);
    for (j = 0; j < num; ++j)
        printf("num:%d, mobile:%s\n", j, (*mobile)[j].mobile);
#endif

    tdestroy(root, free);
    return 0;
}
#define CALLED_FILE_PATH "./test_called_1.csv"

int main(int argc, char *argv[])
{
    Mobile *mobile = NULL;
    FILE *fp = NULL;
    int num = 0;
    struct timeval t_start, t_end;
    gettimeofday(&t_start, NULL);

    fp = fopen(CALLED_FILE_PATH, "r");
    if (!fp)
    {
        printf("AAAAAAAAAAAAA\n");
        exit(-1);
    }

    duplication(fp, &mobile, &num);
    gettimeofday(&t_end, NULL);

    printf("num:%d\n", num);
    printf("毫秒：millisecond:%ld\n", (t_end.tv_sec*1000 + t_end.tv_usec/1000) - (t_start.tv_sec*1000 + t_start.tv_usec/1000));
    printf("微秒：microsecond:%ld\n", (t_end.tv_sec*1000000 + t_end.tv_usec) - (t_start.tv_sec*1000000 + t_start.tv_usec));

    free(mobile);

    return 0;
}

